package com.spsoft.vatoutinv.service.generateinvoice.impl;

import com.spsoft.vatoutinv.constants.OfdConstant;
import com.spsoft.vatoutinv.enums.YhzcbsEnum;
import com.spsoft.vatoutinv.service.generateinvoice.GenerateInvoiceService;
import com.spsoft.vatoutinv.util.ofd.entity.OriginalInvoice;
import com.spsoft.vatoutinv.util.ofd.entity.passenger.PassengerInfo;
import com.spsoft.vatoutinv.util.ofd.entity.passenger.PassengerTransportationInfo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.ofdrw.core.basicStructure.pageObj.layer.Type;
import org.ofdrw.layout.OFDDoc;
import org.ofdrw.layout.PageLayout;
import org.ofdrw.layout.VirtualPage;
import org.ofdrw.layout.element.Div;
import org.ofdrw.layout.element.Paragraph;
import org.ofdrw.layout.element.Position;
import org.ofdrw.layout.element.Span;
import org.ofdrw.layout.element.canvas.Canvas;
import org.ofdrw.layout.element.canvas.DrawContext;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.math.BigDecimal;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.List;

/**
 * @author wangy
 * @date 2024/3/14 9:48
 */
@Slf4j
@Service
public class PassengerTransportationInvoice extends CommonInvoice implements GenerateInvoiceService {
    @Override
    public String generateInvoice(OriginalInvoice originalInvoice, String outPath) throws IOException {
        final Path path = Paths.get(outPath).toAbsolutePath();
        try (OFDDoc ofdDoc = new OFDDoc(path)) {
            // 获取旅客信息明细
            List<PassengerInfo> passengerInfo = originalInvoice.getPassengerInfo();
            // 计算旅客明细所需行数 不同发票类型明细信息不同
            int maxRow = calculateNumberRows(passengerInfo);
            // 根据行数判断是否需要分页 当 42<n行时就需要换页 少于42 默认一页
            int page = maxRow >= 42 ? maxRow / 42 + 1 : 1;
            // 设置一个记录行数的变量 用于后续比生成明细时 通过删减变量判断是否需要翻页
            int tempRow = 0;
            // 设置一个记录明细下标的变量
            int index = 0;
            // 定义当前页面 小计
            // 小计金额
            BigDecimal subTotalAmount = new BigDecimal(0);
            // 小计税额
            BigDecimal subTotalTaxAmount = new BigDecimal(0);
            // 开始遍历每一页
            for (int i = 0; i < page; i++) {
                // 当前页面高度
                double pageHeight = 0D;
                // 当前页面是否为最后一页  用于后续判断是否显示备注
                boolean isLastPage = i == page - 1;
                // 如果 所需明细行数 大于45行 那么就需要换页
                if (maxRow >= 42) {
                    // 获取47行明细的高度
                    pageHeight = calculatePageHeight(47);
                    if (maxRow >= 42) {
                        tempRow = 42;
                    } else {
                        tempRow = maxRow;
                    }
                    maxRow -= 42;
                } else {
                    // 根据明细获取
                    // 因为多了一个上面的 发票明细
                    maxRow += 6;
                    pageHeight = calculatePageHeight(maxRow);
                    if (pageHeight == 140) {
                        tempRow = 8;
                    } else {
                        tempRow = maxRow;
                    }
                }
                // 开始创建页面
                PageLayout pageLayout = ofdDoc.getPageLayout();
                // 设置页面宽度
                pageLayout.setWidth(OfdConstant.INVOICE_MIN_WIDTH);
                // 设置页面高度 A4纸默认大小
                pageLayout.setHeight(pageHeight);
                // 创建虚拟页面
                VirtualPage virtualPage = new VirtualPage(pageLayout);
                // 画图
                Canvas canvas = new Canvas(pageLayout);
                if (isLastPage) {
                    canvas.setDrawer((DrawContext dc) -> {
                        dc.moveTo(4.5315, 2.493);
                        dc.bezierCurveTo(4.5315, 1.368, 3.618, 0.45, 2.4885, 0.45);
                        dc.bezierCurveTo(1.3635, 0.45, 0.45, 1.368, 0.45, 2.493);
                        dc.bezierCurveTo(0.45, 3.618, 1.3635, 4.536, 2.4885, 4.536);
                        dc.bezierCurveTo(3.618, 4.536, 4.5315, 3.618, 4.5315, 2.493);
                        dc.moveTo(1.035, 1.035);
                        dc.lineTo(3.915, 3.915);
                        dc.moveTo(1.035, 3.915);
                        dc.lineTo(3.915, 1.035);
                        dc.stroke();
                    });
                    canvas.setXY(0D, 0D);
                    canvas.setPosition(Position.Absolute);
                    canvas.setLayer(Type.Background);
                    virtualPage.add(canvas);
                }


                // 构建头部标题
                buildHeadTitle(virtualPage, originalInvoice, page, i + 1, outPath);

                // 构建 购买人 销售人
                buildBuyerSeller(virtualPage, originalInvoice);

                // 构建明细信息
                buildDetail(virtualPage, originalInvoice, tempRow, subTotalAmount, subTotalTaxAmount);

                // 构建旅客明细信息
                index = buildMxDetail(virtualPage, originalInvoice, tempRow, index);

                // 构建 底部 合计 小计 备注
                buildBottom(virtualPage, originalInvoice, subTotalAmount, subTotalTaxAmount, isLastPage, pageHeight, canvas);

                // 构建两侧边框 发票识别线
                buildBoderLine(virtualPage, pageHeight);

                // 像ofd文档内添加页面
                ofdDoc.addVPage(virtualPage);
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw e;
        } finally {
            // 删除本地图片
            Paths.get(outPath.substring(0, outPath.lastIndexOf("\\")) + "/eCode.png").toFile().delete();
        }


        return outPath;
    }

    private void buildDetail(VirtualPage virtualPage, OriginalInvoice originalInvoice, int tempRow, BigDecimal subTotalAmount, BigDecimal subTotalTaxAmount) {
        Div div = new Div();
        div.setWidth(201D);
        div.setHeight(22.5D);
        div.setBorder(0.25D);
        div.setBorderColor(159, 0, 15);
        div.setXY(4.5D, 52.1D);
        div.setPosition(Position.Absolute);
        div.setLayer(Type.Background);
        virtualPage.add(div);

        // 项目名称
        Span titleSpan1 = new Span("         项目名称")
                .setFont(kaiFont)
                .setFontSize(3D)
                .setColor(139, 0, 15);
        Paragraph titleSpanP = new Paragraph(37D, 22.5D);
        titleSpanP.setXY(4.5D, 52.1D);
        titleSpanP.setPosition(Position.Absolute);
        titleSpanP.setLayer(Type.Background);
        titleSpanP.add(titleSpan1);
        virtualPage.add(titleSpanP);

        // 规格型号
        Span titleSpan3 = new Span("规格型号")
                .setFont(kaiFont)
                .setFontSize(3D)
                .setColor(139, 0, 15);
        Paragraph titleSpanP3 = new Paragraph(24D, 22.5D);
        titleSpanP3.setXY(41.5D, 52.1D);
        titleSpanP3.setPosition(Position.Absolute);
        titleSpanP3.setLayer(Type.Background);
        titleSpanP3.add(titleSpan3);
        virtualPage.add(titleSpanP3);

        // 单位
        Span titleSpan4 = new Span(" 单 位")
                .setFont(kaiFont)
                .setFontSize(3D)
                .setColor(139, 0, 15);
        Paragraph titleSpanP4 = new Paragraph(12D, 22.5D);
        titleSpanP4.setXY(65.5D, 52.1D);
        titleSpanP4.setPosition(Position.Absolute);
        titleSpanP4.setLayer(Type.Background);
        titleSpanP4.add(titleSpan4);
        virtualPage.add(titleSpanP4);

        // 数量
        Span titleSpan5 = new Span("            数量")
                .setFont(kaiFont)
                .setFontSize(3D)
                .setColor(139, 0, 15);
        Paragraph titleSpanP5 = new Paragraph(25D, 22.5D);
        titleSpanP5.setXY(77.5D, 52.1D);
        titleSpanP5.setPosition(Position.Absolute);
        titleSpanP5.setLayer(Type.Background);
        titleSpanP5.add(titleSpan5);
        virtualPage.add(titleSpanP5);


        // 税率/征收率
        Span titleSpan7 = new Span("             单价")
                .setFont(kaiFont)
                .setFontSize(3D)
                .setColor(139, 0, 15);
        Paragraph titleSpanP7 = new Paragraph(26D, 22.5D);
        titleSpanP7.setXY(102.5D, 52.1D);
        titleSpanP7.setPosition(Position.Absolute);
        titleSpanP7.setLayer(Type.Background);
        titleSpanP7.add(titleSpan7);
        virtualPage.add(titleSpanP7);


        //税额
        Span titleSpan8 = new Span("             金额")
                .setFont(kaiFont)
                .setFontSize(3D)
                .setColor(139, 0, 15);
        // 明细框
        Paragraph titleSpanP8 = new Paragraph(26D, 22.5D);
        titleSpanP8.setXY(128.5D, 52.1D);
        titleSpanP8.setPosition(Position.Absolute);
        titleSpanP8.setLayer(Type.Background);
        titleSpanP8.add(titleSpan8);
        virtualPage.add(titleSpanP8);

        // 税率/征收率
        Span titleSpan6 = new Span("   税率/征收率")
                .setFont(kaiFont)
                .setFontSize(3D)
                .setColor(139, 0, 15);
        Paragraph titleSpanP6 = new Paragraph(25D, 22.5D);
        titleSpanP6.setXY(154.5D, 52.1D);
        titleSpanP6.setPosition(Position.Absolute);
        titleSpanP6.setLayer(Type.Background);
        titleSpanP6.add(titleSpan6);
        virtualPage.add(titleSpanP6);

        // 税额
        Span titleSpan9 = new Span("             税额")
                .setFont(kaiFont)
                .setFontSize(3D)
                .setColor(139, 0, 15);
        Paragraph titleSpanP9 = new Paragraph(27D, 22.5D);
        titleSpanP9.setXY(179.5D, 52.1D);
        titleSpanP9.setPosition(Position.Absolute);
        titleSpanP9.setLayer(Type.Background);
        titleSpanP9.add(titleSpan9);
        virtualPage.add(titleSpanP9);


        // 需要遍历明细信息列表 渲染到页面上
        List<PassengerTransportationInfo> passengerTransportations = originalInvoice.getPassengerTransportations();
        // 每一行需要追加的高度
        double tempHeight = 56.5D;
        for (int i = 0; i < passengerTransportations.size(); i++) {
            // 取出一条明细信息
            PassengerTransportationInfo entity = passengerTransportations.get(i);
            // 计算出每一行明细的所需高度
            // 项目名称高度
            int xmmc = calculateRow(25, entity.getItem());
            int sl = calculateRow(16, entity.getQuantity().toString());
            int dj = calculateRow(17, entity.getPrice().toString());
            int je = calculateRow(17, entity.getAmount().toString());
            // 找出最大值
            int[] arr = {xmmc, sl, dj, je};
            Arrays.sort(arr);

            // 当前行所需高度
            double rowHeight = arr[arr.length - 1] * 4.375D;
            // 定义行间隔变量
            double lineSpace = 0.5D;
            // 如果空间足够
            if (tempRow >= arr[arr.length - 1]) {
                // 减少一条临时行数
                tempRow -= arr[arr.length - 1];
                // 项目名称
                if (StringUtils.isNotEmpty(entity.getItem())) {
                    Span itemSpan = new Span(entity.getItem())
                            .setFontSize(3D)
                            .setColor(0, 0, 0);
                    Paragraph itemP = new Paragraph(37D, rowHeight);
                    if (xmmc <= 1) {
                        itemP.setXY(calculateCenter(37D, 4.5D, entity.getItem()), tempHeight);
                    } else {
                        itemP.setXY(4.5D, tempHeight);
                    }
                    itemP.setPosition(Position.Absolute);
                    itemP.setLayer(Type.Body);
                    itemP.setLineSpace(lineSpace);
                    itemP.add(itemSpan);
                    virtualPage.add(itemP);
                }


                // 数量
                if (ObjectUtils.isNotEmpty(entity.getQuantity()) && entity.getQuantity().compareTo(BigDecimal.ZERO) != 0) {
                    Span quantitySpan = new Span(entity.getQuantity().toString())
                            .setFontSize(3D)
                            .setColor(0, 0, 0);
                    Paragraph quantityP = new Paragraph(25D, rowHeight);
                    if (sl <= 1) {
                        quantityP.setXY(calculateRight(25D, 76.5D, entity.getQuantity().toString()), tempHeight);
                    } else {
                        quantityP.setXY(76.5D, tempHeight);
                    }
                    quantityP.setPosition(Position.Absolute);
                    quantityP.setLayer(Type.Body);
                    quantityP.setLineSpace(lineSpace);
                    quantityP.add(quantitySpan);
                    virtualPage.add(quantityP);
                }


                // 单价
                if (ObjectUtils.isNotEmpty(entity.getPrice()) && entity.getPrice().compareTo(BigDecimal.ZERO) != 0) {
                    Span priceSpan = new Span(entity.getPrice().toString())
                            .setFontSize(3D)
                            .setColor(0, 0, 0);
                    Paragraph priceP = new Paragraph(26D, rowHeight);
                    if (dj <= 1) {
                        priceP.setXY(calculateRight(26D, 102.5D, entity.getPrice().toString()), tempHeight);
                    } else {
                        priceP.setXY(102.5D, tempHeight);
                    }
                    priceP.setPosition(Position.Absolute);
                    priceP.setLayer(Type.Body);
                    priceP.setLineSpace(lineSpace);
                    priceP.add(priceSpan);
                    virtualPage.add(priceP);
                }


                // 金额
                if (ObjectUtils.isNotEmpty(entity.getAmount())) {
                    Span amountSpan = new Span(entity.getAmount().toString())
                            .setFontSize(3D)
                            .setColor(0, 0, 0);
                    Paragraph amountP = new Paragraph(26D, rowHeight);
                    if (je <= 1) {
                        amountP.setXY(calculateRight(26D, 129.5D, entity.getAmount().toString()), tempHeight);
                    } else {
                        amountP.setXY(129.5D, tempHeight);
                    }
                    amountP.setPosition(Position.Absolute);
                    amountP.setLayer(Type.Body);
                    amountP.setLineSpace(lineSpace);
                    amountP.add(amountSpan);
                    virtualPage.add(amountP);
                    // 金额增加
                    subTotalAmount = subTotalAmount.add(entity.getAmount());
                }


                // 税率/征收率
                if (ObjectUtils.isNotEmpty(entity.getTaxScheme())) {
                    String taxScheme = entity.getTaxScheme();
                    if (!"***".equals(entity.getTaxScheme())
                            && !YhzcbsEnum._03.getValue().equals(entity.getTaxScheme())
                            && !YhzcbsEnum._04.getValue().equals(entity.getTaxScheme())) {
                        taxScheme = calculatePercent(taxScheme);
                    }
                    Span taxSchemeSpan = new Span(taxScheme)
                            .setFontSize(3D)
                            .setColor(0, 0, 0);
                    Paragraph taxSchemeP = new Paragraph(25D, rowHeight);
                    taxSchemeP.setXY(calculateCenter(25D, 154.5D, taxScheme), tempHeight);
                    taxSchemeP.setPosition(Position.Absolute);
                    taxSchemeP.setLayer(Type.Body);
                    taxSchemeP.setLineSpace(lineSpace);
                    taxSchemeP.add(taxSchemeSpan);
                    virtualPage.add(taxSchemeP);
                }


                if (ObjectUtils.isNotEmpty(entity.getTaxAmount())) {
                    // 税额
                    Span taxSpan = new Span(entity.getTaxAmount())
                            .setFontSize(3D)
                            .setColor(0, 0, 0);
                    Paragraph taxP = new Paragraph(27D, rowHeight);
                    taxP.setXY(calculateRight(27D, 178.5D, entity.getTaxAmount()), tempHeight);
                    taxP.setLayer(Type.Body);
                    taxP.setPosition(Position.Absolute);
                    taxP.setLineSpace(lineSpace);
                    taxP.add(taxSpan);
                    virtualPage.add(taxP);
                    // 税额增加
                    if (!"***".equals(entity.getTaxAmount())) {
                        subTotalTaxAmount = subTotalTaxAmount.add(new BigDecimal(entity.getTaxAmount()));
                    }
                }
                // 渲染完毕 追加高度 用于下一行渲染
                tempHeight += rowHeight;
            } else {
                break;
            }

        }
        // 合计
        Span totalSpan = new Span("            合        计")
                .setFont(kaiFont)
                .setFontSize(3D)
                .setColor(139, 0, 15);
        Paragraph totalP = new Paragraph(201D, 6D);
        totalP.setXY(4.5D, 70D);
        totalP.setPosition(Position.Absolute);
        totalP.setLayer(Type.Background);
        totalP.add(totalSpan);
        virtualPage.add(totalP);
        // 合计内容
        Span totalAmountSpan = new Span("¥" + originalInvoice.getTaxExclusiveTotalAmount())
                .setFontSize(3D)
                .setColor(0, 0, 0);
        Paragraph totalAmountP = new Paragraph(46D, 6D);
        totalAmountP.setXY(calculateRight(46D, 108.5, "¥" + originalInvoice.getTaxExclusiveTotalAmount()), 70D);
        totalAmountP.setPosition(Position.Absolute);
        totalAmountP.setLayer(Type.Background);
        totalAmountP.add(totalAmountSpan);
        virtualPage.add(totalAmountP);

        // 税额合计
        Span totalTaxSpan = new Span("¥" + originalInvoice.getTaxTotalAmount())
                .setFontSize(3D)
                .setColor(0, 0, 0);
        Paragraph totalTaxP = new Paragraph(47D, 6D);
        totalTaxP.setXY(calculateRight(47D, 158.5D, "¥" + originalInvoice.getTaxTotalAmount()), 70D);
        totalTaxP.setPosition(Position.Absolute);
        totalTaxP.setLayer(Type.Background);
        totalTaxP.add(totalTaxSpan);
        virtualPage.add(totalTaxP);
    }


    private int buildMxDetail(VirtualPage virtualPage, OriginalInvoice originalInvoice, int tempRow, int index) {
        Div div = new Div();
        div.setWidth(201D);
        div.setHeight(4.5D);
        div.setBorder(0.25D);
        div.setBorderTop(0D);
        div.setBorderColor(159, 0, 15);
        div.setXY(4.5D, 74.5D);
        div.setPosition(Position.Absolute);
        div.setLayer(Type.Background);
        virtualPage.add(div);

        // 出行人
        Span titleSpan1 = new Span("     出行人")
                .setFont(kaiFont)
                .setFontSize(3D)
                .setColor(139, 0, 15);
        Paragraph titleSpanP = new Paragraph(20D, 6D);
        titleSpanP.setXY(4.5D, 74.5D);
        titleSpanP.setPosition(Position.Absolute);
        titleSpanP.setLayer(Type.Background);
        titleSpanP.add(titleSpan1);
        virtualPage.add(titleSpanP);

        // 有效身份证号
        Span titleSpan2 = new Span("        有效身份证号")
                .setFont(kaiFont)
                .setFontSize(3D)
                .setColor(139, 0, 15);
        Paragraph titleSpan2P = new Paragraph(38D, 6D);
        titleSpan2P.setXY(24.5D, 74.5D);
        titleSpan2P.setPosition(Position.Absolute);
        titleSpan2P.setLayer(Type.Background);
        titleSpan2P.add(titleSpan2);
        virtualPage.add(titleSpan2P);

        // 出行日期
        Span titleSpan3 = new Span("    出行日期")
                .setFont(kaiFont)
                .setFontSize(3D)
                .setColor(139, 0, 15);
        Paragraph titleSpan3P = new Paragraph(25D, 6D);
        titleSpan3P.setXY(62D, 74.5D);
        titleSpan3P.setPosition(Position.Absolute);
        titleSpan3P.setLayer(Type.Background);
        titleSpan3P.add(titleSpan3);
        virtualPage.add(titleSpan3P);

        // 出发地
        Span titleSpan4 = new Span("          出发地")
                .setFont(kaiFont)
                .setFontSize(3D)
                .setColor(139, 0, 15);
        Paragraph titleSpan4P = new Paragraph(38D, 6D);
        titleSpan4P.setXY(87D, 74.5D);
        titleSpan4P.setPosition(Position.Absolute);
        titleSpan4P.setLayer(Type.Background);
        titleSpan4P.add(titleSpan4);
        virtualPage.add(titleSpan4P);

        // 到达地
        Span titleSpan5 = new Span("          到达地")
                .setFont(kaiFont)
                .setFontSize(3D)
                .setColor(139, 0, 15);
        Paragraph titleSpan5P = new Paragraph(38D, 6D);
        titleSpan5P.setXY(125D, 74.5D);
        titleSpan5P.setPosition(Position.Absolute);
        titleSpan5P.setLayer(Type.Background);
        titleSpan5P.add(titleSpan5);
        virtualPage.add(titleSpan5P);

        // 等级
        Span titleSpan6 = new Span("    等 级")
                .setFont(kaiFont)
                .setFontSize(3D)
                .setColor(139, 0, 15);
        Paragraph titleSpan6P = new Paragraph(17D, 6D);
        titleSpan6P.setXY(163D, 74.5D);
        titleSpan6P.setPosition(Position.Absolute);
        titleSpan6P.setLayer(Type.Background);
        titleSpan6P.add(titleSpan6);
        virtualPage.add(titleSpan6P);


        // 交通工具类型
        Span titleSpan7 = new Span("   交通工具类型")
                .setFont(kaiFont)
                .setFontSize(3D)
                .setColor(139, 0, 15);
        Paragraph titleSpan7P = new Paragraph(24.11D, 6D);
        titleSpan7P.setXY(180.5D, 74.5D);
        titleSpan7P.setPosition(Position.Absolute);
        titleSpan7P.setLayer(Type.Background);
        titleSpan7P.add(titleSpan7);
        virtualPage.add(titleSpan7P);

        // 旅客数据
        List<PassengerInfo> passengerInfo = originalInvoice.getPassengerInfo();

        // 每一行需要追加的高度
        double tempHeight = 80D;
        for (int i = 0; index < passengerInfo.size(); i++) {
            // 取出一条明细信息
            PassengerInfo entity = passengerInfo.get(index);
            // 计算出每一行明细的所需高度
            // 姓名
            int xm = calculateRow(13, entity.getTravelers());
            // 身份证
            int sfz = calculateRow(25, entity.getIdNumber());
            // 出发地
            int cfd = calculateRow(25, entity.getDeparture());
            // 到达地
            int ddd = calculateRow(25, entity.getDestination());
            // 等级
            int dj = calculateRow(11, entity.getGrade());


            int[] arr = {xm, sfz, cfd, ddd, dj};
            Arrays.sort(arr);
            // 当前行所需高度
            double rowHeight = arr[arr.length - 1] * 4.375D;
            // 定义行间隔变量
            double lineSpace = 0.5D;

            if (index == passengerInfo.size() - 1) {
                if (tempRow - arr[arr.length - 1] <= 0) {
                    break;
                }
            }

            if (tempRow >= arr[arr.length - 1]) {
                // 减少一条临时行数
                tempRow -= arr[arr.length - 1];

                // 出行人
                if (StringUtils.isNotEmpty(entity.getTravelers())) {
                    Span travelersSpan = new Span(entity.getTravelers())
                            .setFontSize(3D)
                            .setColor(0, 0, 0);
                    Paragraph travelersP = new Paragraph(20D, rowHeight);
                    if (xm <= 1) {
                        travelersP.setXY(calculateCenter(20D, 4.5D, entity.getTravelers()), tempHeight);
                    } else {
                        travelersP.setXY(4.5D, tempHeight);
                    }
                    travelersP.setPosition(Position.Absolute);
                    travelersP.setLayer(Type.Body);
                    travelersP.setLineSpace(lineSpace);
                    travelersP.add(travelersSpan);
                    virtualPage.add(travelersP);
                }

                // 有效身份证号
                if (StringUtils.isNotEmpty(entity.getIdNumber())) {
                    Span idCardSpan = new Span(entity.getIdNumber())
                            .setFontSize(3D)
                            .setColor(0, 0, 0);
                    Paragraph idCardP = new Paragraph(38D, rowHeight);
                    if (sfz <= 1) {
                        idCardP.setXY(calculateCenter(38D, 24.5D, entity.getIdNumber()), tempHeight);
                    } else {
                        idCardP.setXY(24.5D, tempHeight);
                    }
                    idCardP.setPosition(Position.Absolute);
                    idCardP.setLayer(Type.Body);
                    idCardP.setLineSpace(lineSpace);
                    idCardP.add(idCardSpan);
                    virtualPage.add(idCardP);
                }

                // 出行日期
                if (StringUtils.isNotEmpty(entity.getTravelDate())) {
                    Span travelDateSpan = new Span(entity.getTravelDate())
                            .setFontSize(3D)
                            .setColor(0, 0, 0);
                    Paragraph travelDateP = new Paragraph(25D, rowHeight);
                    travelDateP.setXY(calculateCenter(25D, 62D, entity.getTravelDate()), tempHeight);
                    travelDateP.setPosition(Position.Absolute);
                    travelDateP.setLayer(Type.Body);
                    travelDateP.setLineSpace(lineSpace);
                    travelDateP.add(travelDateSpan);
                    virtualPage.add(travelDateP);
                }

                // 出发地
                if (StringUtils.isNotEmpty(entity.getDeparture())) {
                    Span departureSpan = new Span(entity.getDeparture())
                            .setFontSize(3D)
                            .setColor(0, 0, 0);
                    Paragraph departureP = new Paragraph(38D, rowHeight);
                    if (cfd <= 1) {
                        departureP.setXY(calculateCenter(38D, 87D, entity.getDeparture()), tempHeight);
                    } else {
                        departureP.setXY(87D, tempHeight);
                    }
                    departureP.setPosition(Position.Absolute);
                    departureP.setLayer(Type.Body);
                    departureP.setLineSpace(lineSpace);
                    departureP.add(departureSpan);
                    virtualPage.add(departureP);
                }

                // 到达地
                if (StringUtils.isNotEmpty(entity.getDestination())) {
                    Span destinationSpan = new Span(entity.getDestination())
                            .setFontSize(3D)
                            .setColor(0, 0, 0);
                    Paragraph destinationP = new Paragraph(38D, rowHeight);
                    if (ddd <= 1) {
                        destinationP.setXY(calculateCenter(38D, 125D, entity.getDestination()), tempHeight);
                    } else {
                        destinationP.setXY(125D, tempHeight);
                    }
                    destinationP.setPosition(Position.Absolute);
                    destinationP.setLayer(Type.Body);
                    destinationP.setLineSpace(lineSpace);
                    destinationP.add(destinationSpan);
                    virtualPage.add(destinationP);
                }

                // 等级
                if (StringUtils.isNotEmpty(entity.getGrade())) {
                    Span levelSpan = new Span(entity.getGrade())
                            .setFontSize(3D)
                            .setColor(0, 0, 0);
                    Paragraph levelP = new Paragraph(17D, rowHeight);
                    if (dj <= 1) {
                        levelP.setXY(calculateCenter(17D, 163D, entity.getGrade()), tempHeight);
                    } else {
                        levelP.setXY(163D, tempHeight);
                    }
                    levelP.setPosition(Position.Absolute);
                    levelP.setLayer(Type.Body);
                    levelP.setLineSpace(lineSpace);
                    levelP.add(levelSpan);
                    virtualPage.add(levelP);
                }
                // 交通工具类型
                if (StringUtils.isNotEmpty(entity.getTypeTransportation())) {
                    Span transportTypeSpan = new Span(entity.getTypeTransportation())
                            .setFontSize(3D)
                            .setColor(0, 0, 0);
                    Paragraph transportTypeP = new Paragraph(24.11, rowHeight);
                    transportTypeP.setXY(calculateCenter(24.11, 180.5D, entity.getTypeTransportation()), tempHeight);
                    transportTypeP.setPosition(Position.Absolute);
                    transportTypeP.setLayer(Type.Body);
                    transportTypeP.setLineSpace(lineSpace);
                    transportTypeP.add(transportTypeSpan);
                    virtualPage.add(transportTypeP);
                }
                tempHeight += rowHeight;
                index++;
            } else {
                break;
            }
        }
        return index;
    }


    /**
     * 根据明细信息 计算出所需行数
     *
     * @param goodsInfos
     * @return
     */
    private static int calculateNumberRows(List<PassengerInfo> goodsInfos) {
        int n = 0;
        for (int i = 0; i < goodsInfos.size(); i++) {
            PassengerInfo entity = goodsInfos.get(i);
            int xm = calculateRow(13, entity.getTravelers());
            int sfz = calculateRow(25, entity.getIdNumber());
            int cfd = calculateRow(25, entity.getDeparture());
            int ddd = calculateRow(25, entity.getDestination());
            int dj = calculateRow(11, entity.getGrade());

//            int grade = calculateRow(13, entity.getGrade());
            // 判断最大的高度 累加在n上
            int[] arr = {xm, sfz, cfd, ddd};
            Arrays.sort(arr);
            n += arr[arr.length - 1];
        }
        return n;
    }

}
